<!DOCTYPE HTML>
<html lang="ru" class="light" dir="ltr">
    <head>
        <!-- Book generated using mdBook -->
        <meta charset="UTF-8">
        <title>Описание NRK-PRJ</title>
        <meta name="robots" content="noindex">


        <!-- Custom HTML head -->
        
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="theme-color" content="#ffffff">

        <link rel="icon" href="favicon.svg">
        <link rel="shortcut icon" href="favicon.png">
        <link rel="stylesheet" href="css/variables.css">
        <link rel="stylesheet" href="css/general.css">
        <link rel="stylesheet" href="css/chrome.css">
        <link rel="stylesheet" href="css/print.css" media="print">

        <!-- Fonts -->
        <link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
        <link rel="stylesheet" href="fonts/fonts.css">

        <!-- Highlight.js Stylesheets -->
        <link rel="stylesheet" href="highlight.css">
        <link rel="stylesheet" href="tomorrow-night.css">
        <link rel="stylesheet" href="ayu-highlight.css">

        <!-- Custom theme stylesheets -->

    </head>
    <body class="sidebar-visible no-js">
    <div id="body-container">
        <!-- Provide site root to javascript -->
        <script>
            var path_to_root = "";
            var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light";
        </script>

        <!-- Work around some values being stored in localStorage wrapped in quotes -->
        <script>
            try {
                var theme = localStorage.getItem('mdbook-theme');
                var sidebar = localStorage.getItem('mdbook-sidebar');

                if (theme.startsWith('"') && theme.endsWith('"')) {
                    localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
                }

                if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
                    localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
                }
            } catch (e) { }
        </script>

        <!-- Set the theme before any content is loaded, prevents flash -->
        <script>
            var theme;
            try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
            if (theme === null || theme === undefined) { theme = default_theme; }
            var html = document.querySelector('html');
            html.classList.remove('light')
            html.classList.add(theme);
            var body = document.querySelector('body');
            body.classList.remove('no-js')
            body.classList.add('js');
        </script>

        <input type="checkbox" id="sidebar-toggle-anchor" class="hidden">

        <!-- Hide / unhide sidebar before it is displayed -->
        <script>
            var body = document.querySelector('body');
            var sidebar = null;
            var sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
            if (document.body.clientWidth >= 1080) {
                try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
                sidebar = sidebar || 'visible';
            } else {
                sidebar = 'hidden';
            }
            sidebar_toggle.checked = sidebar === 'visible';
            body.classList.remove('sidebar-visible');
            body.classList.add("sidebar-" + sidebar);
        </script>

        <nav id="sidebar" class="sidebar" aria-label="Table of contents">
            <div class="sidebar-scrollbox">
                <ol class="chapter"><li class="chapter-item expanded "><a href="introduction.html"><strong aria-hidden="true">1.</strong> Введение</a></li><li class="chapter-item expanded "><a href="deploy.html"><strong aria-hidden="true">2.</strong> Инициализация и запуск приложения</a></li><li class="chapter-item expanded "><a href="mail/mail_extractor.html"><strong aria-hidden="true">3.</strong> Работа с почтовыми сообщениями</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="mail/mail_settings.html"><strong aria-hidden="true">3.1.</strong> Добавление и удаление почты для отслеживания</a></li><li class="chapter-item expanded "><a href="mail/mail_extractor.html"><strong aria-hidden="true">3.2.</strong> Отслеживание и извлечение почтовых сообщений</a></li><li class="chapter-item expanded "><a href="mail/attache_mail_extractor.html"><strong aria-hidden="true">3.3.</strong> Извлечение файлов из почтовых сообщений</a></li><li class="chapter-item expanded "><a href="mail/geo_extractor.html"><strong aria-hidden="true">3.4.</strong> Извлечение геолокации из писем</a></li><li class="chapter-item expanded "><a href="mail/mail_find.html"><strong aria-hidden="true">3.5.</strong> Фильтрация/Поиск писем</a></li><li class="chapter-item expanded "><a href="mail/mail_label.html"><strong aria-hidden="true">3.6.</strong> Работа с метками к письму</a></li></ol></li><li class="chapter-item expanded "><a href="appeal/intro_to_appeal.html"><strong aria-hidden="true">4.</strong> Работа с обращениями</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="appeal/mail_to_appeal.html"><strong aria-hidden="true">4.1.</strong> Создание обращения из почтового письма</a></li><li class="chapter-item expanded "><a href="appeal/add_comment.html"><strong aria-hidden="true">4.2.</strong> Добавление комментария к обращению</a></li><li class="chapter-item expanded "><a href="appeal/move_appeal.html"><strong aria-hidden="true">4.3.</strong> Перемещение обращения между колонками (статусами/состояниями)</a></li><li class="chapter-item expanded "><a href="appeal/add_col_kanban.html"><strong aria-hidden="true">4.4.</strong> Добавление новых колонок в раздел "Обращения" и изменение порядка</a></li></ol></li><li class="chapter-item expanded "><a href="post/appeal_to_post.html"><strong aria-hidden="true">5.</strong> Работа с постами</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="post/appeal_to_post.html"><strong aria-hidden="true">5.1.</strong> Создание поста из обращения</a></li><li class="chapter-item expanded "><a href="mail/mailing_label_template.html"><strong aria-hidden="true">5.2.</strong> Настройки шаблонов постов</a></li><li class="chapter-item expanded "><a href="post/to_to.html"><strong aria-hidden="true">5.3.</strong> Быстрый переход от обращения к посту и обратно</a></li><li class="chapter-item expanded "><a href="post/post_find.html"><strong aria-hidden="true">5.4.</strong> Фильтрация/Поиск постов</a></li><li class="chapter-item expanded "><a href="post/post_label.html"><strong aria-hidden="true">5.5.</strong> Метки к посту</a></li><li class="chapter-item expanded "><a href="post/new_attach_for_post.html"><strong aria-hidden="true">5.6.</strong> Редактор: добавить новый файл вложения</a></li><li class="chapter-item expanded "><a href="post/post_attach.html"><strong aria-hidden="true">5.7.</strong> Редактор: добавить видео из вложения</a></li><li class="chapter-item expanded "><a href="post/edit_title_post.html"><strong aria-hidden="true">5.8.</strong> Редактор: редактировать заголовок поста</a></li><li class="chapter-item expanded "><a href="post/edit_date_post.html"><strong aria-hidden="true">5.9.</strong> Редактор: редактировать даты начала и окончания публикации</a></li></ol></li><li class="chapter-item expanded "><a href="public_post.html"><strong aria-hidden="true">6.</strong> Опубликованные посты</a></li><li class="chapter-item expanded affix "><a href="roadmap.html">Дорожная карта</a></li></ol>
            </div>
            <div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
        </nav>

        <!-- Track and set sidebar scroll position -->
        <script>
            var sidebarScrollbox = document.querySelector('#sidebar .sidebar-scrollbox');
            sidebarScrollbox.addEventListener('click', function(e) {
                if (e.target.tagName === 'A') {
                    sessionStorage.setItem('sidebar-scroll', sidebarScrollbox.scrollTop);
                }
            }, { passive: true });
            var sidebarScrollTop = sessionStorage.getItem('sidebar-scroll');
            sessionStorage.removeItem('sidebar-scroll');
            if (sidebarScrollTop) {
                // preserve sidebar scroll position when navigating via links within sidebar
                sidebarScrollbox.scrollTop = sidebarScrollTop;
            } else {
                // scroll sidebar to current active section when navigating via "next/previous chapter" buttons
                var activeSection = document.querySelector('#sidebar .active');
                if (activeSection) {
                    activeSection.scrollIntoView({ block: 'center' });
                }
            }
        </script>

        <div id="page-wrapper" class="page-wrapper">

            <div class="page">
                                <div id="menu-bar-hover-placeholder"></div>
                <div id="menu-bar" class="menu-bar sticky">
                    <div class="left-buttons">
                        <label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
                            <i class="fa fa-bars"></i>
                        </label>
                        <button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
                            <i class="fa fa-paint-brush"></i>
                        </button>
                        <ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
                            <li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
                        </ul>
                        <button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
                            <i class="fa fa-search"></i>
                        </button>
                    </div>

                    <h1 class="menu-title">Описание NRK-PRJ</h1>

                    <div class="right-buttons">
                        <a href="print.html" title="Print this book" aria-label="Print this book">
                            <i id="print-button" class="fa fa-print"></i>
                        </a>

                    </div>
                </div>

                <div id="search-wrapper" class="hidden">
                    <form id="searchbar-outer" class="searchbar-outer">
                        <input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
                    </form>
                    <div id="searchresults-outer" class="searchresults-outer hidden">
                        <div id="searchresults-header" class="searchresults-header"></div>
                        <ul id="searchresults">
                        </ul>
                    </div>
                </div>

                <!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
                <script>
                    document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
                    document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
                    Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
                        link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
                    });
                </script>

                <div id="content" class="content">
                    <main>
                        <h1 id="Программа-для-отслеживания-обращений-граждан-и-создания-на-их-основе-постов"><a class="header" href="#Программа-для-отслеживания-обращений-граждан-и-создания-на-их-основе-постов">Программа для отслеживания обращений граждан и создания на их основе постов.</a></h1>
<p><strong>Описание программы:</strong></p>
<p>Программа предназначена для работы с <code>обращениями</code> граждан поступающих через почту.
Для отслеживания работы с обращениями используется парадигма, известная как канбан - метод управления проектами.</p>
<p>Программа отслеживает почтовые сообщения с разных адресов по протоколу IMAP 
с последующим сохранением вложенных в письмо файлов и текста.</p>
<p>На основе каждого из писем, программа позволяет создать новые <code>обращения</code> 
или добавлять письма к уже существующим обращениям.</p>
<p>В программе реализована функциональность по созданию публично доступных постов
с возможностью их редактирования. Посты создаются на основе <code>обращений</code> и являются связанными.</p>
<p>Все почтовые сообщения и посты являются связанными с <code>обращениями</code>, 
что позволяет выполнить быструю навигацию между ними.</p>
<p>Функциональные особенности приложения:</p>
<ul>
<li>работа с несколькими почтовыми адресами (ящиками).</li>
<li>связь между почтовым сообщением, постом и обращениями.</li>
<li>создание меток этапов работы с обращениями и возможность перемещать обращение с этапа на этап.</li>
<li>WYSIWYG - редактор для постов.</li>
<li>Извлечение геолокации из текста почтового сообщения.</li>
<li>Извлечение геолокации из фотографий приложенных к почтовому сообщению.</li>
<li>Поиск почтовых сообщений и постов по геолокации.</li>
</ul>
<div style="break-before: page; page-break-before: always;"></div><h1 id="Инициализация-и-запуск-приложения"><a class="header" href="#Инициализация-и-запуск-приложения">Инициализация и запуск приложения</a></h1>
<h2 id="Общая-информация"><a class="header" href="#Общая-информация">Общая информация</a></h2>
<p>Приложение написано с использованием языка программирования Rust (Actix Web) и требует выполнить компиляцию приложения.</p>
<p>Для работы приложения также требуется база данных PostgreSQL и обратный прокси сервер (например Traefik).</p>
<p>Для удобства развертывания приложения предлагается использовать Docker контейнеры. 
Структура приложения с использованием Docker контейнеров следующая:</p>
<ul>
<li>db_server - Сервер баз данных. Используется PostgreSQL.</li>
<li>db-backup_db_server - Содержит скрип выполнения резервных копий базы данных. 
Скрипт хранит копии за сегодня, 7 дней, 4 недели, 12 месяцев. </li>
<li>backend_workers_imap - Сервис по отслеживанию сообщений на почте. </li>
<li>backend_ssr - Сервис с пользовательским Web интерфейсом.</li>
<li>proxy - Обратный прокси сервер. Используется Traefik.</li>
</ul>
<h2 id="Запуск-в-docker-контейнерах"><a class="header" href="#Запуск-в-docker-контейнерах">Запуск в Docker контейнерах.</a></h2>
<ol>
<li>
<p><strong>Копирование папки <code>dist</code></strong></p>
<p>Скомпилированное приложение в виде бинарных файлов содержится в папке <code>dist</code>. 
В этой папке также содержатся все необходимые конфигурационные файлы 
для запуска приложения, включая файл <code>docker-compose.dist.yml</code>. 
В нем описывается запуск всех необходимых для работы контейнеров. </p>
</li>
<li>
<p><strong>Настройка переменных окружения</strong></p>
<p>При Запуске приложения в docker контейнере,
предлагается в корне проекта создать файл <code>.env</code> со следующими ключами:</p>
<pre><code class="language-dotenv"># Уровень регистрации сообщений приложения (debug, info, error).
LOG_LEVEL=info
#
# =============================
# Настройки сервера базы данных и доступа к ней.
# =============================
# 
# Имя суперпользователя.
POSTGRES_USER=
# Пароль суперпользователя.
POSTGRES_PASSWORD=
# Наименование (хост имя) базы данных (Должно соответсвовать наименованию docker контейнера).
POSTGRES_SERVER=
#
# =============================
# Настройки доступа к базе данных для приложения.
# =============================
#
# Имя пользователя БД, под которым будет выполнять подключчение к БД приложение.
USER_POSTGRES_USER=
# Пароль пользователя БД, под которым будет выполнять подключчение к БД приложение.
USER_POSTGRES_PASSWORD=
# Наименование базы данных в сервере баз данных.
USER_POSTGRES_DB=
#
# =============================
# Настройки дирректории хранения файлов.
# =============================
#
# Путь к дирректории в которой должны храниться файлы загружаемые через сервисы.
PATH_TO_FILE_STORE=/usr/local/share/file_store
#
# =============================
# Настройки SSR (Web интерфейса)
# =============================
#
# Доменное имя по которому усуществляется доступ к приложению.
DOMAIN=
# Имя пользователя для Базовой аутентификации к административной(не публичной) части интерфейса.
ADMIN_BACKEND_SSR_AUTH_USER=
# Пароль пользователя для Базовой аутентификации к административной(не публичной) части интерфейса.
# пароль должен быть хеширован с использованием MD5, SHA1 или BCrypt.
ADMIN_BACKEND_SSR_AUTH_PASS=
# Адрес почты для получения сертификата от let's encrypt 
EMAIL_CERTIFICATESRESOLVERS=
</code></pre>
</li>
<li>
<p><strong>Запуск приложения</strong></p>
<p>В корне папки <code>dist</code> находится <code>./command.dist.sh</code> файл в котором описана скрипты запуска и остановки приложения:</p>
<ul>
<li><strong>start</strong> - Команда запуска приложения. Если ранее не была выполнена сборка docker образов,
то перед запуском будет выполнена сборка.</li>
<li><strong>stop</strong> - Выполнение команды остановит приложение.</li>
<li><strong>build</strong> - Команда сборки docker образов.</li>
<li><strong>restart</strong> - Перезапуск приложения.</li>
</ul>
<p>Пример: Для старта приложения необходимо выполнить команду</p>
<pre><code class="language-shell">./command.dist.sh start 
</code></pre>
</li>
</ol>
<h2 id="Сборка-приложения-из-исходного-кода-программы-и-запуск-в-docker-контейнерах"><a class="header" href="#Сборка-приложения-из-исходного-кода-программы-и-запуск-в-docker-контейнерах">Сборка приложения из исходного кода программы и запуск в Docker контейнерах.</a></h2>
<p>Запуск приложения из исходного кода аналогичен запуску готового приложения, 
но требует наличие папки с исходным текстом программ. </p>
<pre><code>Внимание. Сборка проекта из исходного кода может потребованить значительное время и 
навыки работы с языком программирования Rust. Так как сборка выполняется внутри docker контейнера, 
нет необходимости на хостовой машине устанавливать инструменты разработчика и компилятор Rust.
</code></pre>
<ol>
<li>
<p><strong>Копирование исходного текста программы</strong></p>
<p>Для начала, необходимо скопировать исходный текст программы в выбранную вами директорию.</p>
</li>
<li>
<p><strong>Настройка переменных окружения</strong></p>
<p>При сборке и запуске приложения в docker контейнере, 
предлагается в корне проекта создать файл <code>.env</code>. 
Содержание фала с параметрами окружения аналогично описанному выше.</p>
</li>
<li>
<p><strong>Сборка и запуск приложения</strong></p>
<p>В корне проекта находится <code>./command.sh</code> файл в котором описана скрипты запуска и остановки приложения:</p>
<ul>
<li><strong>start</strong> - Команда запуска приложения. Если ранее не была выполнена сборка docker образов,
то перед запуском будет выполнена сборка.</li>
<li><strong>stop</strong> - Выполнение команды остановит приложение.</li>
<li><strong>build</strong> - Команда сборки docker образов.</li>
<li><strong>restart</strong> - Перезапуск приложения.</li>
</ul>
<p>Прежде чем приступать к запуску приложения,
необходимо выполнить настройку приманных окружения, необходимых для работы приложения.
Для старта приложения необходимо выполнить команду</p>
<pre><code class="language-shell">./command.sh start 
</code></pre>
</li>
</ol>
<div style="break-before: page; page-break-before: always;"></div><h1 id="Отслеживание-и-извлечение-почтовых-сообщений"><a class="header" href="#Отслеживание-и-извлечение-почтовых-сообщений">Отслеживание и извлечение почтовых сообщений</a></h1>
<p>Приложение позволяет работать с почтовыми ящиками через 
протокол <a href="https://ru.wikipedia.org/wiki/IMAP">IMAP</a>.</p>
<p>Количество почтовых ящиков (пока что) не ограничено. 
Можно <a href="mail/../mail/mail_settings.html">подключать</a> сразу несколько почтовых ящиков.</p>
<p>Все сообщения отправленные на почту в раздел <code>Входищие (INBOX)</code>
будут зарегистрированы приложением и сохранены в БД.</p>
<p><img src="mail/../img/send_mail.gif" alt="send_mail.gif" /></p>
<p>Порядок действий на видео:</p>
<ul>
<li>заходим в почту, создаем новое письмо и вводим текст;</li>
<li>отправляем письмо;</li>
<li>проверяем отобразилось ли письмо в программе 
(в левой навигационной панели);</li>
<li>для просмотра щелкаем по карточке письма и его 
содержимое будет отображено в правой-рабочей области.</li>
</ul>
<div style="break-before: page; page-break-before: always;"></div><h1 id="Добавление-и-удаление-почты-для-отслеживания"><a class="header" href="#Добавление-и-удаление-почты-для-отслеживания">Добавление и удаление почты для отслеживания</a></h1>
<p>Для добавления новой почты к отслеживанию необходимо перейти в раздел <code>Настройки</code>.
Панель настроек разделена на две части: вертикальная панель навигации и область настроек.</p>
<p><img src="mail/../img/setting_page.png" alt="img.png" /></p>
<p>В вертикальной панели навигации необходимо выбрать пункт <code>Почта</code>, 
при этом в области настроек должны отобразиться настройки почты.</p>
<p>Первым разделом настроек почты является раздел содержащий <code>Список отслеживаемых почтовых ящиков</code>.
Если ранее еще не были добавлены почтовые адреса для отслеживания, 
то список будет пустым.</p>
<p>Для добавления нового адреса необходимо нажать на кнопку <code>Добавить почтовый ящик</code>, 
после чего будет отрыто модальное окно с формой ввода:</p>
<ul>
<li>
<p>Адрес почтового сервера (IMAP)</p>
<p><em>пример: imap.yandex.ru</em></p>
</li>
<li>
<p>Порт (IMAP)</p>
<p><em>пример: 993</em></p>
</li>
<li>
<p>Адрес почты</p>
<p><em>пример: mybeautifulmail@yandex.ru</em></p>
</li>
<li>
<p>Пароль или ключ доступа</p>
</li>
</ul>
<p><img src="mail/../img/setting_mail_new.png" alt="img.png" /></p>
<p>После добавления почты в список отслеживаемых, 
все письма с постового сервера будут дублироваться в приложении.</p>
<p><img src="mail/../img/setting_mail_new_succ.png" alt="img.png" /></p>
<blockquote>
<p>Примечание: По умолчанию отслеживаются только письма из папки INBOX (Входящие)</p>
</blockquote>
<div style="break-before: page; page-break-before: always;"></div><h1 id="Отслеживание-и-извлечение-почтовых-сообщений-1"><a class="header" href="#Отслеживание-и-извлечение-почтовых-сообщений-1">Отслеживание и извлечение почтовых сообщений</a></h1>
<p>Приложение позволяет работать с почтовыми ящиками через 
протокол <a href="https://ru.wikipedia.org/wiki/IMAP">IMAP</a>.</p>
<p>Количество почтовых ящиков (пока что) не ограничено. 
Можно <a href="mail/../mail/mail_settings.html">подключать</a> сразу несколько почтовых ящиков.</p>
<p>Все сообщения отправленные на почту в раздел <code>Входищие (INBOX)</code>
будут зарегистрированы приложением и сохранены в БД.</p>
<p><img src="mail/../img/send_mail.gif" alt="send_mail.gif" /></p>
<p>Порядок действий на видео:</p>
<ul>
<li>заходим в почту, создаем новое письмо и вводим текст;</li>
<li>отправляем письмо;</li>
<li>проверяем отобразилось ли письмо в программе 
(в левой навигационной панели);</li>
<li>для просмотра щелкаем по карточке письма и его 
содержимое будет отображено в правой-рабочей области.</li>
</ul>
<div style="break-before: page; page-break-before: always;"></div><h1 id="Извлечение-файлов-из-почтовых-сообщений"><a class="header" href="#Извлечение-файлов-из-почтовых-сообщений">Извлечение файлов из почтовых сообщений</a></h1>
<p>Если к письму будут прикреплены файлы, 
то они будут выгружены и сохранены в указанной 
при настройке приложения папке.</p>
<p>Сейчас поддерживается работа с файлами <code>mp4</code>, <code>jpg</code>, <code>png</code> и <code>pdf</code>.
Другие форматы файлов игнорируются. </p>
<p><img src="mail/../img/attach.gif" alt="attach.gif" /></p>
<p>Порядок действий на видео:</p>
<ul>
<li>заходим в почту, создаем новое письма и прикрепляем файл;</li>
<li>отправляем письмо;</li>
<li>проверяем отобразилось ли письмо в программе 
(в левой навигационной панели);</li>
<li>для просмотра щелкаем по карточке письма и его 
содержимое будет отображено в правой-рабочей области;</li>
<li>под областью с текстом находится горизонтальный контейнер в 
котором содержатся файлы из письма;</li>
<li>при щелчке ЛКМ по иконке файла будет открыто модальное окно с 
демонстрацией содержимого файла.</li>
</ul>
<div style="break-before: page; page-break-before: always;"></div><h1 id="Извлечение-геолокации-из-писем"><a class="header" href="#Извлечение-геолокации-из-писем">Извлечение геолокации из писем</a></h1>
<p>Имеется два встроенных механизма фиксации геолокации:</p>
<ol>
<li>Если геолокация (широта и долгота) указана в тексте письма.</li>
<li>Если геолокация записана в файле (например в файле фотографии).</li>
</ol>
<p>После извлечения координат из письма они записываются в БД. 
Также, выполняется попытка определения названия города, района, улицы, дома.
Благодаря сохранению геолокации можно выполнять <a href="mail/mail_find.html">поиск писем</a> 
по названию города, района, улицы, дома.</p>
<h2 id="Координаты-в-тексте"><a class="header" href="#Координаты-в-тексте">Координаты в тексте</a></h2>
<p><img src="mail/../img/geo_text.gif" alt="geo_text.gif" /></p>
<p>Порядок действий на видео:</p>
<ul>
<li>заходим в почту, создаем новое письмо в тексте которого указываем кооржинаты;</li>
<li>отправляем письмо;</li>
<li>проверяем отобразилось ли письмо в программе 
(в левой навигационной панели);</li>
<li>для просмотра щелкаем по карточке письма и его 
содержимое будет отображено в правой-рабочей области;</li>
<li>над областью с текстом по центру находится выпадающий список с перечнем зарегистрированных локаций;</li>
<li>при щелчке ЛКМ по элементу из списка будет открыто новое окно с картой.</li>
</ul>
<h2 id="Координаты-в-фотографии"><a class="header" href="#Координаты-в-фотографии">Координаты в фотографии</a></h2>
<p><img src="mail/../img/geo_attach.gif" alt="geo_attach.gif" /></p>
<p>Порядок действий на видео:</p>
<ul>
<li>заходим в почту, создаем новое письмо и прикрепляем файл 
в котором хранится информация о координатах;</li>
<li>отправляем письмо;</li>
<li>проверяем отобразилось ли письмо в программе 
(в левой навигационной панели);</li>
<li>для просмотра щелкаем по карточке письма и его 
содержимое будет отображено в правой-рабочей области;</li>
<li>над областью с текстом по центру находится выпадающий список с перечнем зарегистрированных локаций;</li>
<li>при щелчке ЛКМ по элементу из списка будет открыто новое окно с картой.</li>
</ul>
<div style="break-before: page; page-break-before: always;"></div><h1 id="ФильтрацияПоиск-писем"><a class="header" href="#ФильтрацияПоиск-писем">Фильтрация/Поиск писем</a></h1>
<p>Все письма располагаются списком в левой части. 
По умолчанию список содержит 25 последних писем удовлетворяющих условиям фильтра/поиска.
В конце списка располагается кнопка &quot;Больше писем&quot;, 
которая проверит есть ли еще письма в БД и добавит их в конец списка.</p>
<p>Доступна фильтрация по дате создания письма:</p>
<ul>
<li>за все время;</li>
<li>за сегодня;</li>
<li>за вчера;</li>
<li>за неделю;</li>
<li>за месяц.</li>
</ul>
<p>Поиск работает по теме письма или по локации письма. 
Можно указать город (улицу, район) и если у письма есть 
геометка с этим городом, то оно покажется в списке.</p>
<p><img src="mail/../img/mail_find.gif" alt="mail_find.gif" /></p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="Метки-к-письму"><a class="header" href="#Метки-к-письму">Метки к письму</a></h1>
<p>К каждому письму можно назначить несколько меток. </p>
<p><img src="mail/../img/mail_label2.gif" alt="mail_label.gif" /></p>
<p>Порядок действий на видео:</p>
<ul>
<li>над областью с текстом письма слева находится выпадающий список с 
перечнем доступных меток для письма;</li>
<li>при выборе или отмены выбора изменения автоматически сохранятся в БД.</li>
</ul>
<div style="break-before: page; page-break-before: always;"></div><h1 id="Работа-с-обращениями"><a class="header" href="#Работа-с-обращениями">Работа с обращениями</a></h1>
<p>Каждое входящие сообщение может послужить основой для создания нового <code>обращения</code> 
или может быть добавлено к уже существующему <code>обращению</code>.</p>
<p>Работа с обращениями организована процесс разбитый на этапы. 
Количество и порядок этапов работы с обращениями настраивается в разделе настроек. 
Минимально допустимое количество этапов - два и они уже созданы по умолчанию и не могут быть удалены.</p>
<p>Перенос обращения с этапа на этап осуществляется путем перетаскивания обращения из одной колонки этапа в другую.</p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="Создание-обращения-из-почтового-письма"><a class="header" href="#Создание-обращения-из-почтового-письма">Создание обращения из почтового письма</a></h1>
<p>На основе каждого письма можно создать <code>обращение</code>. </p>
<p>Также письмо можно привязать уже к созданному <code>обращению</code>.</p>
<p><img src="appeal/../img/mail_to_appeal.gif" alt="mail_label.gif" /></p>
<p>Порядок действий на видео:</p>
<ul>
<li>Перейдите в раздел <code>Входящие</code> и в списке не обработанных новых сообщений выберите интересующее вас сообщение.</li>
<li>При выборе сообщения в списке будет показано содержимое письма. 
В нижней части будут располагаться элементы управления при помощи которых можно или удалить письмо, 
или создать на его основе <code>обращение</code>.</li>
<li>При выборе <code>Отправить в обращения</code> (или введя номер и нажав <code>Связать с обращением</code>) письмо будет преобразовано в новое обращение.
Далее доступ к содержимому письма можно будет получить из карточки обращения.</li>
<li>Для быстрого перехода к карточке обращения можно воспользоваться кнопкой `` расположенной в правом верхнем углу окна с письмом.</li>
</ul>
<div style="break-before: page; page-break-before: always;"></div><h1 id="Добавление-комментария-к-обращению"><a class="header" href="#Добавление-комментария-к-обращению">Добавление комментария к обращению</a></h1>
<p>К каждому <code>обращению</code> можно добавлять комментарии.</p>
<p>Комментарии - это некоторый текст привязанный ко времени и к обращению.
Через комментарии можно оставлять важные пометки и напоминания связанные с этим обращением.</p>
<p><img src="appeal/../img/appeal_add_comment.gif" alt="mail_label.gif" /></p>
<p>Порядок действий на видео:</p>
<ul>
<li>Перейдите в раздел <code>Обращения</code>. Каждое обращение показывается в виде карточки. 
Карточки распределены между колонок в зависимости от текущего статуса (состояния) обращения.</li>
<li>В правом нижнем углу карточки показано количество комментариев к ней.</li>
<li>При выборе карточки будет открыто модальное окно с содержимым карточки обращения.</li>
<li>В нижней части окна с содержимым обращения расположена строка ввода комментариев.</li>
</ul>
<div style="break-before: page; page-break-before: always;"></div><h1 id="Перемещение-обращения-между-колонками-статусамисостояниями"><a class="header" href="#Перемещение-обращения-между-колонками-статусамисостояниями">Перемещение обращения между колонками (статусами/состояниями)</a></h1>
<p>Работа с <code>обращениями</code> ведется с использованием методики kanban.
Изменение состояния работы с обращениями можно выполнить путем переноса карточки <code>обращения</code><br />
из одной в другую колонки.</p>
<p>При перемещении карточки с одной колонки в другую будет добавлен новый комментарий.</p>
<p><img src="appeal/../img/move_appeal.gif" alt="mail_label.gif" /></p>
<p>Порядок действий на видео:</p>
<ul>
<li>Перейдите в раздел <code>Обращения</code>. Каждое обращение показывается в виде карточки. 
Все новые <code>обращения</code> создаются в первой колонке с названием <code>Обращения</code>.</li>
<li>Если зажать ЛКМ над карточкой и выполнить перенос ее из одной колонки в другую и отжать ЛКМ, 
то будет выполнен перенос <code>обращения</code> в новое состояние.</li>
</ul>
<div style="break-before: page; page-break-before: always;"></div><h1 id="Добавление-новых-колонок-в-раздел-Обращения-и-изменение-порядка"><a class="header" href="#Добавление-новых-колонок-в-раздел-Обращения-и-изменение-порядка">Добавление новых колонок в раздел &quot;Обращения&quot; и изменение порядка</a></h1>
<p><img src="appeal/../img/new_col_kanban.gif" alt="new_col_kanban.gif" /></p>
<p>Для добавления новых колонок в раздел &quot;Обращения&quot; или изменения их порядка необходимо перейти в раздел <code>Настройки</code>.
Панель настроек разделена на две части: вертикальная панель навигации и область настроек.</p>
<p><img src="appeal/../img/setting_page.png" alt="img.png" /></p>
<p>В вертикальной панели навигации необходимо выбрать пункт <code>Обращения</code>, 
при этом в области настроек должны отобразиться настройки почты.</p>
<p>Первым разделом настроек обращений является раздел содержащий <code>Категории состояний работы с обращением</code>.
Если ранее еще не были добавлены новые категории, 
то список будет состоять из двух категорий: Обращения и Исполнено.</p>
<p>Для добавления новой категории необходимо нажать на кнопку <code>Новоя категория</code>, 
после чего будет отрыто модальное окно с формой ввода:</p>
<ul>
<li>Название категории</li>
<li>Описание категории</li>
</ul>
<p><img src="appeal/../img/settings_add_col_kanban.png" alt="img.png" /></p>
<p>При работе с категориями доступна возможность изменять их порядок, редактировать заглавие и описания, а также их удаление.</p>
<blockquote>
<blockquote>
<p>Примечание: Программа запрещает удалять категории в которых в настоящий момент времени есть обращения.</p>
</blockquote>
</blockquote>
<div style="break-before: page; page-break-before: always;"></div><h1 id="Создание-поста-из-обращения"><a class="header" href="#Создание-поста-из-обращения">Создание поста из обращения</a></h1>
<p>На основе содержимого обращений можно быстро создать пост.</p>
<p><img src="post/../img/create_post_for_appeal.gif" alt="post_attach_mail.gif" /></p>
<p>Если для обращения еще не создан (привязан) ни один пост, 
то в правой части обращения будет находиться кнопка с текстом <code>Постов нет</code>, 
при наведении на которую будет раскрыт список с кнопкой <code>Создать пост</code>.</p>
<p>При успешном создании поста, кнопка с текстом <code>Постов нет</code> будет заменена 
на кнопку с текстом указывающим на количество постов связанных с обращением.</p>
<p>Между постом и обращением будет связь, позволяющая выполнить быстрый переход.</p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="Создание-поста-из-обращения-1"><a class="header" href="#Создание-поста-из-обращения-1">Создание поста из обращения</a></h1>
<p>На основе содержимого обращений можно быстро создать пост.</p>
<p><img src="post/../img/create_post_for_appeal.gif" alt="post_attach_mail.gif" /></p>
<p>Если для обращения еще не создан (привязан) ни один пост, 
то в правой части обращения будет находиться кнопка с текстом <code>Постов нет</code>, 
при наведении на которую будет раскрыт список с кнопкой <code>Создать пост</code>.</p>
<p>При успешном создании поста, кнопка с текстом <code>Постов нет</code> будет заменена 
на кнопку с текстом указывающим на количество постов связанных с обращением.</p>
<p>Между постом и обращением будет связь, позволяющая выполнить быстрый переход.</p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="Настройки-шаблонов-постов"><a class="header" href="#Настройки-шаблонов-постов">Настройки шаблонов постов</a></h1>
<p>Для каждого входящего почтового сообщения можно <a href="mail/../mail/mail_label.html">назначить</a> 
одну или более почтовых меток.</p>
<p>При создании поста из почтового сообщения для которого выбрана одна и более меток, 
при формировании текста поста будет подставлен соответсвующий шаблон.</p>
<p>Для редактирования шаблонов постов привязанных к меткам, необходимо перейти в раздел <code>Настройки</code>.
Панель настроек разделена на две части: вертикальная панель навигации и область настроек.</p>
<p>В вертикальной панели навигации необходимо выбрать пункт <code>Посты</code>,
при этом в области настроек должны отобразиться настройки почты.</p>
<p>Редактирование шаблонов выполняется в разделе <code>Шаблоны постов для меток писем</code>.</p>
<p><img src="mail/../img/mail_label_template.png" alt="img.png" /></p>
<p>В левой части содержится список меток почты. 
При выборе нужной метке в правой части появится поле для редактирования.</p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="Быстрый-переход-от-обращения-к-посту-и-обратно"><a class="header" href="#Быстрый-переход-от-обращения-к-посту-и-обратно">Быстрый переход от обращения к посту и обратно</a></h1>
<p>Если пост был создан из обращения, то между ними образуется связь, 
позволяющая выполнять быстрый переход от обращения к посту на эту тему.</p>
<p><img src="post/../img/to_to.gif" alt="to_to.gif" /></p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="ФильтрацияПоиск-постов"><a class="header" href="#ФильтрацияПоиск-постов">Фильтрация/Поиск постов</a></h1>
<p>Поиск постов в левой панели работает аналогично поиску писем. 
Если пост был создан от письма у которого присутствовали геометки, 
то при выполнении поиска по постам, можно также искать по названию городов и улиц.</p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="Метки-к-посту"><a class="header" href="#Метки-к-посту">Метки к посту</a></h1>
<p>Аналогично как с письмами, для постов можно назначать метки.
Стоит отметить, что метки писем и метки постов - это разные метки. </p>
<p><img src="post/../img/post_label.gif" alt="post_label.gif" /></p>
<p>Порядок действий на видео:</p>
<ul>
<li>над областью с текстом письма слева находится выпадающий список с 
перечнем доступных меток для поста;</li>
<li>при выборе или отмены выбора изменения автоматически сохранятся в БД.</li>
</ul>
<div style="break-before: page; page-break-before: always;"></div><h1 id="Редактор-добавить-новый-файл-вложения"><a class="header" href="#Редактор-добавить-новый-файл-вложения">Редактор: добавить новый файл вложения</a></h1>
<p>Для поста можно добавить новый файл вложения, 
который после можно использовать при редактировании текста поста.</p>
<p>Все приложенные файлы будут связанны с постом, что позволит держать их всегда под рукой.</p>
<p>Для добавления нового файла вложения необходимо нажать кнопку <code>Прикрепить</code> и 
в открывшемся окне выбрать файл, который вы хотите прикрепить.</p>
<p>Ограничение: Размер файла не должен превышать 25 Мб.</p>
<p><img src="post/../img/new_attachment_for_post.gif" alt="new_attachment_for_post.gif" /></p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="Редактор-добавить-видео-из-вложения"><a class="header" href="#Редактор-добавить-видео-из-вложения">Редактор: добавить видео из вложения</a></h1>
<p>Редактор постов позволяет добавлять видео ролики и картинки к тексту.</p>
<p>Справа от области редактирования текста располагается блок с вложениями.
Вложения делятся на два вида:</p>
<ul>
<li>вложения поста;</li>
<li>вложения писем от которых был создан пост.</li>
</ul>
<p>Для добавления видео в текст необходимо зажать ЛКМ над изображением файла и 
перетянуть его в область редактирования текста, 
не отпуская ЛКМ до момента попадания курсора в область редактирования текста.</p>
<p><img src="post/../img/post_attach_mail.gif" alt="post_attach_mail.gif" /></p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="Редактор-редактировать-заголовок-поста"><a class="header" href="#Редактор-редактировать-заголовок-поста">Редактор: редактировать заголовок поста</a></h1>
<p>Заголовок поста задается отдельно от текста поста. </p>
<p>В верхней части редактора присутствует поле для ввода текста. </p>
<p>Запрещается оставлять строку заголовка пустой, 
использовать более 256 символов или использовать запрещенные символы.</p>
<p>Все изменения происходят автоматически (задержка 1 сек). 
Если изменения были сохранены в БД, то поле будет подсвечено зеленым цветом.
Иначе - красным.</p>
<p><img src="post/../img/edit_title_post.gif" alt="edit_title_post.gif" /></p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="Редактор-редактировать-даты-начала-и-окончания-публикации"><a class="header" href="#Редактор-редактировать-даты-начала-и-окончания-публикации">Редактор: редактировать даты начала и окончания публикации</a></h1>
<p>Каждый созданный пост не является опубликованным. 
Для его публикации необходимо выбрать дату начала публикации. 
Функциональные элементы отвечающие за задание даты начала публикации 
располагаются в нижней части редактора.</p>
<p>Также, у поста может быть задана дата окончания публикации. 
Если дата окончания не выбрана, то пост считается бессрочным. </p>
<p>Все изменения автоматически сохраняются в БД.</p>
<p><img src="post/../img/edit_date_post.gif" alt="edit_title_post.gif" /></p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="Опубликованные-посты"><a class="header" href="#Опубликованные-посты">Опубликованные посты</a></h1>
<h2 id="Публикация-постов"><a class="header" href="#Публикация-постов">Публикация постов</a></h2>
<p>Все <a href="post/edit_date_post.html">опубликованные</a> посты становятся публично 
доступными в витрине постов.</p>
<p><img src="img/publication_start_post.gif" alt="publication_start_post.gif" /></p>
<h2 id="Просмотр-постов"><a class="header" href="#Просмотр-постов">Просмотр постов</a></h2>
<p>На одну страницу помещается не более 25 постов. 
Внизу страницы имеются кнопки <code>вперед</code> и <code>назад</code> для перелистывания страниц. </p>
<p>Каждый опубликованный пост имеет две формы отображения: <code>краткую</code> и <code>полную</code>.</p>
<p>В краткой форме пост представлен в виде карточки состоящей из двух частей: левой и правой. 
Слева располагается медиа контент из поста. Если в посте сразу несколько фотографий, 
то в левой части появляются стрелки прокрутки контента.
Справа расположен текст поста, без медиа контента. Если текст очень длинный, 
то отображается лишь небольшая часть текста, а полное содержимое доступно 
в <code>полной</code> форме поста по ссылке по <code>Посмотреть все</code>.</p>
<p>В полной форме поста текст и медиа контент в нем расположен в том виде, как его редактировал автор.</p>
<p><img src="img/view_post.gif" alt="view_post.gif" /></p>
<h2 id="Поиск-среди-опубликованных-постов"><a class="header" href="#Поиск-среди-опубликованных-постов">Поиск среди опубликованных постов</a></h2>
<p>Параметры поиска:</p>
<ul>
<li>Период публикации - За сегодня, за вчера, за неделю, за месяц, за все время (по умолчанию)</li>
<li>По категориям - По умолчанию в фильтре отмечены все категории постов, 
но пользователь может самостоятельно отметить наиболее интересующие его категории.</li>
<li>По заголовку или месту (геометки) - Если к посту указана геометка, 
то можно выполнить поиск по локации (название города, региона, название улицы).</li>
</ul>
<p><img src="img/filter_view_post.gif" alt="filter_view_post.gif" /></p>
<pre><code>На анимации выше можно видеть как в разделе фильтра в поле ввода текста вводится город Екатеринбург. 
Так как Пост с картинкой был создан из письма с геометкой, то он (пост) унаследовал эту геометку. 
Теперь пост можно найти по названию города или улицы.  </code></pre>
<div style="break-before: page; page-break-before: always;"></div><h1 id="Дорожная-карта-проекта"><a class="header" href="#Дорожная-карта-проекта">Дорожная карта проекта</a></h1>
<ul>
<li><strong>Добавить возможность создания поста без привязки к почтовому сообщению.</strong></li>
<li><strong>Необходимо добавить генерацию RSS.</strong> Одним из источников размещения постов является площадка dzen.ru.
Данная площадка, помимо ручного добавление статей, позволяет автоматически &quot;подхватывать&quot; статьи из RSS. 
RSS разметка должна соответствовать требованиям dzen.ru.</li>
<li><strong>Групповая публикация постов</strong> Необходимо добавить возможность выбирать сразу несколько постов и выполнить групповую публикацию.
Также, так как предусмотрена отложенная публикация, то можно сделать групповую отложенную публикацию с распределением по времени.</li>
<li><strong>Создание поста из нескольких сообщений, а не из одного</strong> Сейчас работает правило &quot;одно сообщение - один пост&quot;. 
Однако, в реальности может потребоваться объединить несколько сообщений в один пост. 
Для этого нужно будет выделить несколько сообщений и в меню действий выбрать пункт &quot;Создать пост&quot;.</li>
<li><strong>Удаление сообщений</strong> Необходимо добавить возможность скрывать не релевантные сообщения (удалять их), 
что бы они не &quot;захламляли&quot; список сообщений.</li>
<li><strong>Авто генерацию текста поста с использованием GigaChat</strong> <em>Тут потребуется платный доступ, 
так как &quot;хороший&quot; промт может занимать много токенов.</em></li>
<li><strong>Если это возможно, то наладить автопубликацию в новый сайт НК (тот что на WordPress)</strong></li>
<li><strong>Добавить фирменной стилистики</strong></li>
</ul>

                    </main>

                    <nav class="nav-wrapper" aria-label="Page navigation">
                        <!-- Mobile navigation buttons -->


                        <div style="clear: both"></div>
                    </nav>
                </div>
            </div>

            <nav class="nav-wide-wrapper" aria-label="Page navigation">

            </nav>

        </div>




        <script>
            window.playground_copyable = true;
        </script>


        <script src="elasticlunr.min.js"></script>
        <script src="mark.min.js"></script>
        <script src="searcher.js"></script>

        <script src="clipboard.min.js"></script>
        <script src="highlight.js"></script>
        <script src="book.js"></script>

        <!-- Custom JS scripts -->

        <script>
        window.addEventListener('load', function() {
            window.setTimeout(window.print, 100);
        });
        </script>

    </div>
    </body>
</html>
